#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>

int main() {
    // 1. 使用open()创建并打开文件src_file，并设置文件权限为：用户可可读写，组和其他用户只读
    int src_fd = open("src_file", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (src_fd == -1) {
        perror("open src_file failed");
        exit(EXIT_FAILURE);
    }

    // 2. 使用write()向src_file文件中写入字符串“hello world！”，并使用read()读取文件内容输出到终端
    const char *write_str = "hello world！\n";
    ssize_t bytes_written = write(src_fd, write_str, strlen(write_str));
    if (bytes_written == -1) {
        perror("write to src_file failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }

    // 将文件指针移到文件开头，准备读取
    lseek(src_fd, 0, SEEK_SET);

    char read_buf[1024];
    ssize_t bytes_read = read(src_fd, read_buf, sizeof(read_buf) - 1);
    if (bytes_read == -1) {
        perror("read from src_file failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }
    read_buf[bytes_read] = '\0'; // 确保读取的内容是有效的字符串
    printf("File content after writing:\n%s\n", read_buf);

    // 3. 使用fcntl()对文件src_file加写入锁，使用write()向文件中追加字符串“This is an appended text.”，释放文件锁
    struct flock lock;
    lock.l_type = F_WRLCK; // 写锁
    lock.l_whence = SEEK_END; // 从文件末尾开始
    lock.l_start = 0;
    lock.l_len = 0; // 锁定从当前位置到文件末尾

    if (fcntl(src_fd, F_SETLK, &lock) == -1) {
        perror("fcntl set write lock failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }

    const char *append_str = "This is an appended text.\n";
    ssize_t append_bytes = write(src_fd, append_str, strlen(append_str));
    if (append_bytes == -1) {
        perror("append to src_file failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }

    // 解锁
    lock.l_type = F_UNLCK;
    if (fcntl(src_fd, F_SETLK, &lock) == -1) {
        perror("fcntl unlock failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }

    // 将文件指针移到文件开头，准备读取
    lseek(src_fd, 0, SEEK_SET);

    bytes_read = read(src_fd, read_buf, sizeof(read_buf) - 1);
    if (bytes_read == -1) {
        perror("read from src_file after append failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }
    read_buf[bytes_read] = '\0';
    printf("File content after appending:\n%s\n", read_buf);

    // 4. 使用lseek()函数和write()函数将文件src_file中的“world”替换为“Linux”
    // 查找"world"的位置
    char *world_pos = strstr(read_buf, "world");
    if (world_pos != NULL) {
        off_t offset = world_pos - read_buf;
        if (lseek(src_fd, offset, SEEK_SET) == -1) {
            perror("lseek to 'world' position failed");
            close(src_fd);
            exit(EXIT_FAILURE);
        }

        const char *replace_str = "Linux";
        ssize_t replace_bytes = write(src_fd, replace_str, strlen(replace_str));
        if (replace_bytes == -1) {
            perror("replace 'world' with 'Linux' failed");
            close(src_fd);
            exit(EXIT_FAILURE);
        }
    } else {
        printf("'world' not found in the file.\n");
    }

    // 将文件指针移到文件开头，准备读取
    lseek(src_fd, 0, SEEK_SET);

    bytes_read = read(src_fd, read_buf, sizeof(read_buf) - 1);
    if (bytes_read == -1) {
        perror("read from src_file after replacement failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }
    read_buf[bytes_read] = '\0';
    printf("File content after replacement:\n%s\n", read_buf);

    // 5. 使用lseek()、read()和write()等函数将源文件src_file中的后半部分数据复制到目标文件dest_file中，目标文件dest_file存取许可权和源文件src_file相同
    struct stat src_stat;
    if (fstat(src_fd, &src_stat) == -1) {
        perror("fstat src_file failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }

    off_t file_size = src_stat.st_size;
    off_t half_size = file_size / 2;

    // 打开或创建目标文件，设置与源文件相同的权限
    int dest_fd = open("dest_file", O_RDWR | O_CREAT, src_stat.st_mode);
    if (dest_fd == -1) {
        perror("open dest_file failed");
        close(src_fd);
        exit(EXIT_FAILURE);
    }

    // 将源文件指针移到中间位置
    if (lseek(src_fd, half_size, SEEK_SET) == -1) {
        perror("lseek src_file to middle failed");
        close(src_fd);
        close(dest_fd);
        exit(EXIT_FAILURE);
    }

    // 读取源文件后半部分
    ssize_t remaining_bytes = file_size - half_size;
    char *buffer = (char *)malloc(remaining_bytes);
    if (buffer == NULL) {
        perror("malloc buffer failed");
        close(src_fd);
        close(dest_fd);
        exit(EXIT_FAILURE);
    }

    bytes_read = read(src_fd, buffer, remaining_bytes);
    if (bytes_read == -1) {
        perror("read from src_file for copying failed");
        free(buffer);
        close(src_fd);
        close(dest_fd);
        exit(EXIT_FAILURE);
    }

    // 写入目标文件
    ssize_t bytes_written_dest = write(dest_fd, buffer, bytes_read);
    if (bytes_written_dest == -1 || bytes_written_dest != bytes_read) {
        perror("write to dest_file failed");
        free(buffer);
        close(src_fd);
        close(dest_fd);
        exit(EXIT_FAILURE);
    }

    free(buffer);

    // 6. 使用close()函数关闭文件
    close(src_fd);
    close(dest_fd);

    printf("All operations completed successfully.\n");

    return 0;
}